﻿using Furion.DatabaseAccessor;
using Furion.DependencyInjection;
using Furion.FriendlyException;
using IndoorPosition.Server.Core.Entities;
using IndoorPosition.Server.Core.Utils;
using Mapster;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace IndoorPosition.Server.Application
{
    /// <summary>
    /// 蓝牙基站业务逻辑代码
    /// </summary>
    public class StationService : IStationService, ITransient
    {
        IRepository<Station> _stationRepository;
        IRepository<Position> _positionRepository;
        IRepository<Floor> _floorRepository;

        public StationService(IRepository<Station> stationRepository, IRepository<Position> positionRepository, IRepository<Floor> floorRepository)
        {
            _stationRepository = stationRepository;
            _positionRepository = positionRepository;
            _floorRepository = floorRepository;
        }

        /// <summary>
        /// 添加基站
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<int> AddAsync(StationInputDto input)
        {
            var existFloor = await _floorRepository.Where(f => f.Id == input.FloorId).AnyAsync();
            if (!existFloor)
            {
                throw Oops.Oh("楼层ID不正确");
            }
            var exist = await _stationRepository.Where(s => s.UUID == input.UUID).AnyAsync();
            if (exist)
            {
                throw Oops.Oh("已经存在具有相同UUID的基站");
            }
            var station = input.Adapt<Station>();
            var result = await _stationRepository.InsertNowAsync(station);
            return result.Entity.Id;
        }

        /// <summary>
        /// 删除基站
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task DeleteAsync(int id)
        {
            await _stationRepository.DeleteNowAsync(id);
        }

        /// <summary>
        /// 更新基站信息
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task UpdateAsync(StationInputDto input)
        {
            var station = await _stationRepository.Where(s => s.UUID == input.UUID).FirstOrDefaultAsync();
            station.Model = input.Model;
            station.Board = input.Board;
            station.IBeaconName = input.IBeaconName;
            station.MeasuredPower = input.MeasuredPower;
            station.TransmissionPower = input.TransmissionPower;
            station.BroadcastInterval = input.BroadcastInterval;
            station.MAC = input.MAC;
            station.UUID = input.UUID;
            station.Major = input.Major;
            station.Minor = input.Minor;
            station.Minor = input.Minor;
            station.Battery = input.Battery;
            await _stationRepository.UpdateNowAsync(station);
        }

        /// <summary>
        /// 获取某一个基站信息
        /// </summary>
        /// <param name="uuid"></param>
        /// <returns></returns>
        public async Task<StationDto> GetAsync(string uuid)
        {
            var station = await _stationRepository.Where(s => s.UUID == uuid).Include("Position").Include("Floor").FirstOrDefaultAsync();
            if (station == null)
            {
                throw Oops.Oh("传入的UUID不正确");
            }
            return station.Adapt<StationDto>();
        }

        /// <summary>
        /// 获取所有基站
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<List<StationDto>> ListAllAsync(SearchInputDto input)
        {
            var query = _stationRepository.AsQueryable();
            if (!string.IsNullOrEmpty(input.Keyword))
            {
                query = query.Where(s => s.Model.Contains(input.Keyword) || s.Board.Contains(input.Keyword) || s.IBeaconName.Contains(input.Keyword));
            }
            if (input.Conditions != null && input.Conditions.Count > 0)
            {
                query = query.Where(LambdaExpressionBuilder.BuildLambda<Station>(input.Conditions));
            }
            var stationList = await query.Include("Position").Include("Floor").ToListAsync();
            return stationList.Adapt<List<StationDto>>();
        }

        /// <summary>
        /// 分页获取基站
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<PagedList<StationDto>> ListAsync(PageInputDto input)
        {
            var query = _stationRepository.AsQueryable();
            if (!string.IsNullOrEmpty(input.Keyword))
            {
                query = query.Where(s => s.Model.Contains(input.Keyword) || s.Board.Contains(input.Keyword) || s.IBeaconName.Contains(input.Keyword));
            }
            if (input.Conditions != null && input.Conditions.Count > 0)
            {
                query = query.Where(LambdaExpressionBuilder.BuildLambda<Station>(input.Conditions));
            }
            var stationPageList = await query.Include("Position").Include("Floor").ToPagedListAsync(input.Page,input.Size);
            return stationPageList.Adapt<PagedList<StationDto>>();
        }

        /// <summary>
        /// 获取某一楼层的所有基站
        /// </summary>
        /// <param name="floorId"></param>
        /// <returns></returns>
        public async Task<List<StationDto>> ListByFloorAsync(int floorId)
        {
            var stationList = await _stationRepository.Where(s=>s.FloorId == floorId).Include("Position").ToListAsync();
            return stationList.Adapt<List<StationDto>>();
        }

        /// <summary>
        /// 设置基站位置
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task SetPositionAsync(PositionInputDto input)
        {
            var position = await _positionRepository.Where(p => p.StationId == input.StationId).FirstOrDefaultAsync();
            if (position != null)
            {
                position.X = input.X;
                position.Y = input.Y;
                await _positionRepository.UpdateNowAsync(position);
            }
            else
            {
                var existStation = await _stationRepository.Where(s=>s.Id == input.StationId).AnyAsync();
                if (!existStation)
                {
                    throw Oops.Oh("基站ID不正确");
                }
                position = input.Adapt<Position>();
                await _positionRepository.InsertNowAsync(position);
            }
        }
    }
}
